package com.zhongying.jf.util.sign;

import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.security.*;
import java.util.HashMap;
import java.util.Map;

public class SignUtil {
    private static final Logger logger = LoggerFactory.getLogger(SignUtil.class);

    //生成密钥对
    public static Map<String, String> generatorKey(String filePath) {
        Map<String, String> map = new HashMap<>();
        try {
            KeyPair pair = SignatureUtils.generateRsaKeyPair(2048);
            map.put("publicKey", Base64.encodeBase64String(pair.getPublic().getEncoded()));
            map.put("privateKey", Base64.encodeBase64String(pair.getPrivate().getEncoded()));
            // 将密钥对写入到文件
            FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");
            FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");
            BufferedWriter pubbw = new BufferedWriter(pubfw);
            BufferedWriter pribw = new BufferedWriter(prifw);
            pubbw.write(map.get("publicKey"));
            pribw.write(map.get("privateKey"));
            pubbw.flush();
            pubbw.close();
            pubfw.close();
            pribw.flush();
            pribw.close();
            prifw.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.error("生成密钥对失败:{}", ex.getMessage());
        }
        return map;
    }

    //生成签名
    public static String sign(String privateStr, Map dataMap) {
        String retval = "";
        try {
            String data = JSON.toJSONString(dataMap);
            PrivateKey privateKey = SignatureUtils.getRsaPkcs8PrivateKey(Base64.decodeBase64(privateStr));
            byte[] sign = SignatureUtils.sign(SignatureAlgorithm.SHA1WithRSA, privateKey, data);
            retval = Base64.encodeBase64String(sign);
        } catch (GeneralSecurityException ex) {
            ex.printStackTrace();
            logger.error("生成签名失败:{}", ex.getMessage());
        }
        return retval;
    }

    //签名验证
    public static boolean verify(String publicKeyStr, String sign, Map<String, String> dataMap) {
        boolean flag = false;
        try {
            String data = JSON.toJSONString(dataMap);
            PublicKey key = SignatureUtils.getRsaX509PublicKey(Base64.decodeBase64(publicKeyStr));
            flag = SignatureUtils.verify(SignatureAlgorithm.SHA1WithRSA, key, data, Base64.decodeBase64(sign));
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.error("签名验证失败:{}", ex.getMessage());
        }
        return flag;
    }

    /**
     * 从文件中读取秘钥
     * @param FilePath 秘钥文件位置
     * @param fileName 秘钥文件名(带后缀名)
     * @return 秘钥字符串
     * @throws Exception
     */
    public static String loadKeyByFile(String FilePath,String fileName) throws Exception {
        try {
            BufferedReader br = new BufferedReader(new FileReader(FilePath
                    + "/"+fileName));
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        } catch (IOException e) {
            throw new Exception(fileName+"秘钥数据读取错误");
        } catch (NullPointerException e) {
            throw new Exception(fileName+"秘钥输入流为空");
        }
    }


    public static void main(String[] args) {
//        //生成密钥对
//        Map<String, String> map = generatorKey();
//        String privateStr = map.get("privateKey");
//        String publicKeyStr = map.get("publicKey");
        //加载密钥对
        String privateStr = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCrS9j4D4P5ZUrB2U1CFodNk6Mc5Pf6d1E/x78Y74r+PDxt7jRit1fFTdcafT+L83e/C1qGFb+vZCOLv6JeMm8KCts8dGkrUBNEb4CzUTv/u07R3cSpC+UGHGSyQd6KKN2LzYXyZ8/r7EUZYvxYagQvHCMIsC+KQNLsLpX8vIUk03KabNLjdOq7dXqPzMuIXTRv6rkJfRFTtq0TeLwQIYvqYYLs5KiLmPSdg5D7c/7VkL7rbPvvLO0X5QStI5A4YKPfGwaRf2xJVZi5SwZcAHxM9i1q09UO1i+H0yecFZds7t1oD1DMWxY4MW0r/Po+slrVTe+PKfU+CbIYvDPlJma/AgMBAAECggEAULDyDCiC6sCkbpyGoFMseYbKl5nklsAOLhVSF9T/jLOjY8WKN9ZWKkN4yKmnfa27Auu+QNuN6HkrpXEoc2cel4R1sgzEXfrimKJN5iqmMNlzT7lAIsHPqQlHBhGxWzPU6T5vkrkEYQZzpnnSlXObdPW0KyuTuXS/5zIqxVuo/Kc5UQ6y619Wl9+7lB8U4S0DWbsDe/8nMb7T1kCe1edHVn5RoOir86gn8tI6kXorLJXQ0w4FQTCk7c3SFV5TDByBrv4F1bOTx2u+Yvvj81IdbqNArUNDz6Hj4HnzXisfV8tk+gK/Y35gxtRUd9cYaZOLAFRkeuLSRYUlCHR4XL0DAQKBgQDTBIdhqR563ww2/iusaS/j6gJuL+xaJ/H8DkCON8Wsr7gVeJssilLencUe7diqK+3MSoSq+FM/QV1qitXhmeAu4ScHW3zwLdpV2tWaJCD39BCUGJ3Qov4cQX5fRIVsCqHkDPyynXIqvFHhtTzJtkgqzrCGR+sHhzH2QXKbI+QnLwKBgQDPz61JeVcmf0kxoCKsFryAbgoD8TnrG0Q2yGqe1OzHKrGWD00Gv8OAg4pTPcunIbNr0lbVYd8iaFGagW3rTHHhfh8Trb0mG549X5nI90aIySLExL6qYED+W8bJVgzGD57LzYJA/gl05Ng4X6KquQIQjJ+gelUK93YP+l44ntnVcQKBgDcqTu40FTjQCNRznB1FnnR538rIkoR7PuLDIxNK902O3pQWZJK/UqzKGBde3K6YL2Gh9Y7wvmqh/vb0dre0z4vR5q8gtsffZN3fCMp0OX44+wCMcu1xPvdKE+x58FtvaCVDU+iqCoerlcho5gxhr/oo8LMaKBJewKv9LiXquyGXAoGBAIVeN0xMP45JamQa7aWcAeY6uNrG2fD1UtYF0ceVx1AbKlWwBDMspv+3a/L4WdctXcT4/Rl88oNWh+is4Cp+qSealb8/ZYErgGbLEBtV90KaM2ItEmCt3Yhgxjc4roH+TF9nyQyE/PS0Wb/0QKVojtaoKVoIqMOdBXxDpmyYJh1BAoGAAlNRIVnVgB8vBph3Ri5Vl9u7yEiToBhhVho+1g3U7upHiye+mpLW2WSdzdkSL9w6V7SYYj0WHZthYGO3zSgwkGGhLmzcr4EX7nucxfZe6vQoq+emvT1qYrWcHSqfpx4zi/5q27mh9yv0YCteUBZtp81HE0bgfX3TOnMeNscGy6Y=";
        String publicKeyStr ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq0vY+A+D+WVKwdlNQhaHTZOjHOT3+ndRP8e/GO+K/jw8be40YrdXxU3XGn0/i/N3vwtahhW/r2Qji7+iXjJvCgrbPHRpK1ATRG+As1E7/7tO0d3EqQvlBhxkskHeiijdi82F8mfP6+xFGWL8WGoELxwjCLAvikDS7C6V/LyFJNNymmzS43Tqu3V6j8zLiF00b+q5CX0RU7atE3i8ECGL6mGC7OSoi5j0nYOQ+3P+1ZC+62z77yztF+UErSOQOGCj3xsGkX9sSVWYuUsGXAB8TPYtatPVDtYvh9MnnBWXbO7daA9QzFsWODFtK/z6PrJa1U3vjyn1PgmyGLwz5SZmvwIDAQAB";
       /* try {
            privateStr = loadKeyByFile("G:\\","privateKey.keystore");
        } catch (Exception e) {
            e.printStackTrace();
        }
        String publicKeyStr = null;
        try {
            publicKeyStr = loadKeyByFile("G:\\","publicKey.keystore");
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        //待签名数据
        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("x1", "我们");
        dataMap.put("x2", "是");
        dataMap.put("x3", "中国人");
        //生成签名
        String sign = sign(privateStr, dataMap);
        System.out.println("-------->"+sign);
        //验签
        boolean isOk = verify(publicKeyStr, sign, dataMap);
        System.err.println("ok:" + isOk);
    }

}
